﻿

using Daemon.Data.Substructure.Helpers;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.ChangeTracking;
using Microsoft.EntityFrameworkCore.Design;
using Microsoft.EntityFrameworkCore.Infrastructure;
using System;
using System.Collections.Generic;
using System.Linq;

namespace Daemon.Model
{
    public partial class ApiDBContent : DbContext
    {

        public ApiDBContent(DbContextOptions<ApiDBContent> options) : base(options)
        {

        }

        public ApiDBContent()
        {

        }

        public DbSet<AdminFile> AdminFile { get; set; }

        public DbSet<SecuredItemGroup> SecuredItemGroup { get; set; }

        public DbSet<SecuredItem> SecuredItem { get; set; }

        public DbSet<RoleSecuredItem> RoleSecuredItem { get; set; }

        public DbSet<ClientConfig> ClientConfig { get; set; }

        public DbSet<UserLog> UserLog { get; set; }

        public DbSet<TokenInfo> TokenInfo { get; set; }

        public DbSet<UserSession> UserSession { get; set; }

        public DbSet<UserRole> UserRole { get; set; }

        public DbSet<AdminRole> AdminRole { get; set; }

        public DbSet<AdminUser> AdminUser { get; set; }

        public DbSet<GenerateConfig> GenerateConfig { get; set; }

        public DbSet<DatabaseConfig> DatabaseConfig { get; set; }
        public DbSet<LogRuleMonitoringField> LogRuleMonitoringField { get; set; }

        public DbSet<LogEntityEventTrackedChange> LogEntityEventTrackedChange { get; set; }

        public DbSet<LogRuleCalculatedField> LogRuleCalculatedField { get; set; }

        public DbSet<LogEntityHardcodedValue> LogEntityHardcodedValue { get; set; }

        public DbSet<LogRule> LogRule { get; set; }

        public DbSet<LogEntityEvent> LogEntityEvent { get; set; }

        public DbSet<LogEntry> LogEntry { get; set; }

        public DbSet<LogEntityMeta> LogEntityMeta { get; set; }

        public DbSet<LogEntityFKMeta> LogEntityFKMeta { get; set; }

        public DbSet<LogRuleReport> LogRuleReport { get; set; }

        public DbSet<AdminDictionary> AdminDictionary { get; set; }

        public DbSet<FormTemplate> FormTemplate { get; set; }

        public DbSet<RoleApplication> RoleApplication { get; set; }

        public DbSet<Application> Application { get; set; }

        public DbSet<CommonCity> CommonCity { get; set; }

        public DbSet<DatasourceConfig> DatasourceConfig { get; set; }

        public DbSet<ProjectInfo> ProjectInfo { get; set; }

        public DbSet<StudentClass> StudentClasses { get; set; }

        public DbSet<StudentGrade> StudentGrade { get; set; }

        public DbSet<Student> Student { get; set; }

        public DbSet<StudentSubject> StudentSubjects { get; set; }

        public DbSet<StudentStage> StudentStages { get; set; }

        public DbSet<StudentImportTemplate> StudentImportTemplates { get; set; }

        public DbSet<ScoreImportTemplate> ScoreImportTemplates { get; set; }

        public DbSet<StudentScore> StudentScores { get; set; }

        public DbSet<AttachmentTree> AttachmentTrees { get; set; }

        public DbSet<StudentSchool> StudentSchools { get; set; }
        public DbSet<StudentScoreGrid> StudentScoreGrid { get; set; }
        public DbSet<PublicShared> publicShared { get; set; }
        public DbSet<SystemMenu> SystemMenus { get; set; }
        public DbSet<WxConfig> WxConfigs { get; set; }
        public DbSet<Department> Departments { get; set; }
        public DbSet<UserDepartment> UserDepartments { get; set; }
        public DbSet<FormDataSource> FormDataSources { get; set; }
        public DbSet<FormDataSourceOption> FormDataSourceOptions { get; set; }

        protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
        {
            optionsBuilder.ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>();
        }

        public override int SaveChanges()
        {
            var entities = ChangeTracker.Entries().ToArray();
            var addedEntities = GetEntities(entities.Where(p => p.State == EntityState.Added));
            var changedEntities = GetEntities(entities.Where(p => p.State == EntityState.Modified));
            var deletedEntities = GetEntities(entities.Where(p => p.State == EntityState.Deleted));
            var result = base.SaveChanges();

            if (deletedEntities.Any())
            {
                NotificationHelper.Instance.OnEntitiesDeleted?.Invoke(deletedEntities);
            }

            if (addedEntities.Any())
            {
                NotificationHelper.Instance.OnEntitiesAdded?.Invoke(addedEntities);
            }

            if (changedEntities.Any())
            {
                NotificationHelper.Instance.OnEntitiesChanged?.Invoke(changedEntities);
            }
            return result;
        }

        private Dictionary<Type, List<object>> GetEntities(IEnumerable<EntityEntry> sourceEntities)
        {
            var entitiesDict = new Dictionary<Type, List<object>>();

            foreach (var entity in sourceEntities.Select(r => r.Entity))
            {
                var entityType = entity.GetType();
                if (!entitiesDict.TryGetValue(entityType, out List<object> list))
                {
                    list = new List<object>() { entity };
                    entitiesDict.Add(entityType, list);
                    continue;
                }

                list.Add(entity);
            }

            return entitiesDict;
        }
    }

    public class ApplicationContextDbFactory : IDesignTimeDbContextFactory<ApiDBContent>
    {
        ApiDBContent IDesignTimeDbContextFactory<ApiDBContent>.CreateDbContext(string[] args)
        {
            var optionsBuilder = new DbContextOptionsBuilder<ApiDBContent>();
            string connectionStr = "Server=101.33.254.90;port=3306;Database=exam_score;uid=root;pwd=123qwe!@#;pooling=true;CharSet=utf8";
            optionsBuilder.UseMySql<ApiDBContent>(connectionStr, Microsoft.EntityFrameworkCore.ServerVersion.Parse("5.7.27-log")).ReplaceService<IModelCacheKeyFactory, DynamicModelCacheKeyFactory>().UseQueryTrackingBehavior(QueryTrackingBehavior.NoTracking);

            return new ApiDBContent(optionsBuilder.Options);
        }
    }

    //class SchemaModelCacheFactory : IModelCacheKeyFactory
    //{
    //    public object Create(DbContext context) => new SchemaModelCache(context);
    //}


    //class SchemaModelCache : ModelCacheKey
    //{
    //    readonly string _schema;
    //    public SchemaModelCache(DbContext context) : base(context)
    //    {
    //        _schema = (context as ApiDBContent)?.CurrentScheme
    //    }
    //}
    //public class DynamicModelCacheKeyFactory : IModelCacheKeyFactory
    //{
    //    public object Create(DbContext context)
    //    {
    //        if (context is ApiDBContent apiDbContent)
    //        {
    //            return (context.GetType());
    //        }
    //        return context.GetType();
    //    }
    //}
}
